package com.sjx.jtt809.server.codec;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.sjx.jtt809.server.pojo.Response;
import com.sjx.jtt809.server.pojo.ResponseFactory;
import com.sjx.jtt809.server.util.ConstantJtt809Util;
import com.sjx.jtt809.server.util.HexBytesUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

/**
 * jtt809解码类
 */
public class DecoderJtt809 extends ByteToMessageDecoder {

    private static final Log logger = LogFactory.get();

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {

        // region 报文转义
        byte[] bytes = Unpooled.copiedBuffer(in).array();
        ByteBuf finalBytebuf = Unpooled.buffer();

        formatBuffer(bytes, finalBytebuf);

        byte[] bytesTemp = Unpooled.copiedBuffer(finalBytebuf).array();
        logger.info("======================> 报文转义 : {}", HexBytesUtil.bytesToHex(bytesTemp));
        // end region

        int msgId = finalBytebuf.getUnsignedShort(ConstantJtt809Util.MSG_ID_INDEX_OF_PACKAGE);
        try {
            // 工厂根据传入的指令实例化对象
            Response response = ResponseFactory.createResponse(msgId, finalBytebuf);
            if (null != response) {
                out.add(response);
            }
        } finally {
            in.clear();
        }
    }

    /**
     * 报文解码
     *
     * @param bytes
     * @param formatBuffer
     */
    private static void formatBuffer(byte[] bytes, ByteBuf formatBuffer) {
        for (int i = 0; i <= bytes.length; i++) {
            // 获取当前元素的下一个元素
            int nextByte = 0;

            // i 超过所能读取的字节数时，退出（假设byte数组长度为92，最大下标为91，当下标为92时，退出）
            if (i > (bytes.length - 1)) {
                break;
            }

            // i < 能读取的字节数时，获取下一个可读（假设byte数组长度为92，最大下标为91，当下标为90时，可取到91）
            if (i < (bytes.length - 1)) {
                nextByte = bytes[i + 1];
            }
            switch (bytes[i]) {
                case 0x5a:
                    byte[] formatByte0x5a = new byte[1];

                    // 0x5a 0x01 ---> 0x5b
                    if (nextByte == 0x01) {
                        formatByte0x5a[0] = 0x5b;
                        i++;
                    }

                    // 0x5a 0x02 ---> 0x5a
                    if (nextByte == 0x02) {
                        formatByte0x5a[0] = 0x5a;
                        i++;
                    }
                    formatBuffer.writeBytes(formatByte0x5a);
                    break;
                case 0x5e:
                    byte[] formatByte0x5e = new byte[1];

                    // 0x5e 0x01 ---> 0x5d
                    if (nextByte == 0x01) {
                        formatByte0x5e[0] = 0x5d;
                        i++;
                    }

                    // 0x5e 0x02 ---> 0x5e
                    if (nextByte == 0x02) {
                        formatByte0x5e[0] = 0x5e;
                        i++;
                    }
                    formatBuffer.writeBytes(formatByte0x5e);
                    break;
                default:
                    formatBuffer.writeByte(bytes[i]);
                    break;
            }
        }
    }
}
